/*
 * File:   ParticleSystemParser.cpp
 * Author: RedEyedKiller
 *
 * Created on 20 Αύγουστος 2010, 12:22 πμ
 */

#include <list>
#include <vector>
#include "tinyxml.h"
#include "../physics/ParticleSystem.h"
#include "ParticleSystemParser.h"
#include "../Vector2.h"
#include "../Logger.h"

namespace TiXML
{
class TiXmlElement;
}

namespace FileParser
{
using namespace physicsSystem::particleSystem;

ParticleSystemParser::ParticleSystemParser(const char* name, ParticleSystem* system) : fname(name)
{
    this->system = system;
}

bool ParticleSystemParser::ParseSystem()
{
    //Load file
    TiXML::TiXmlDocument xFile( fname.c_str( ) );
    if( !xFile.LoadFile( ) )
    {
        LOG( Logger::CHANNEL_LOADING, LogFileStream::LEVEL_ERROR ) << "Error parsing " << fname << " file not loaded. :" << xFile.ErrorDesc( );
        return false;
    }

    //get the root of the file : ParticleSystem
    TiXML::TiXmlElement* xPartSystem = xFile.FirstChildElement( "ParticleSystem" );
    if( !xPartSystem )
    {
        LOG( Logger::CHANNEL_LOADING, LogFileStream::LEVEL_ERROR ) << "Error parsing " << fname << " root not loaded.";
        return false;
    }

    ParseIncludeList( xPartSystem );

    //Read Root attributes
    {
        int crTh, cache;
        cache = 0;
        emiter.maxParts = ParseValue<int>( xPartSystem->Attribute( "partsPerEmiter" ) );
        xPartSystem->Attribute( "creationThreashold", &crTh );
        xPartSystem->Attribute( "cache", &cache );
        std::string name = xPartSystem->Attribute( "name" );
        std::string camera = xPartSystem->Attribute( "camera" );
        const char* blending = xPartSystem->Attribute( "blending" );
        if( blending != NULL )
        {
            system->SetBlending( gl::GetBlendingMethodName( blending ) );
        }

        system->SetMapCollisions( ParseValue<bool>( xPartSystem->Attribute( "mapCollisions" ) ) );
        system->SetName( name );
        system->SetCreationThreashold( crTh );
        if( cache == 0 )
            cache = 20;
        system->SetMaxCachedEmiters( cache );
        if( camera == "wrap" )
        {
            system->SetCameraBeh( ParticleSystem::CB_WRAP );
        }
        else if( camera == "follow" )
        {
            system->SetCameraBeh( ParticleSystem::CB_FOLLOW );
        }
        else
        {
            system->SetCameraBeh( ParticleSystem::CB_NORMAL );
        }
    }

    ParseParticle( xPartSystem->FirstChildElement( "Particle" ) );
    ParseEmiter( xPartSystem->FirstChildElement( "EmiterPrototype" ) );
    system->SetPrototype( emiter );
    xPartSystem->Clear( );
    xFile.Clear( );

    return true;
}

bool ParticleSystemParser::ParseParticle(TiXML::TiXmlElement* xPart)
{
    if( !xPart )
    {
        return false;
    }

    std::string str;
    xPart->Attribute( "lifetime", &emiter.lifetime );
    str = xPart->Attribute( "fileName" );
    system->SetClip( Parse<Math::Rect > ( xPart->Attribute( "clip" ) ) );
    system->SetResource( str );
    {
        TiXML::TiXmlElement* xMass = xPart->FirstChildElement( "Mass" );
        emiter.minMass = ParseValue<float>( xMass->Attribute( "minValue" ) );
        emiter.maxMass = ParseValue<float>( xMass->Attribute( "maxValue" ) );
        xMass->Clear( );
    }
    {
        TiXML::TiXmlElement* xColor = xPart->FirstChildElement( "Color" );
        emiter.birthColor = ParseValue<gl::Color > ( xColor->Attribute( "birth" ) );
        emiter.deathColor = ParseValue<gl::Color > ( xColor->Attribute( "death" ) );
        xColor->Clear( );
    }
    {
        TiXML::TiXmlElement* xScale = xPart->FirstChildElement( "Scale" );
        emiter.birthScale = ParseValue<Math::Vector2F > ( xScale->Attribute( "birth" ) );
        emiter.deathScale = ParseValue<Math::Vector2F > ( xScale->Attribute( "death" ) );
        emiter.scaleVariation = ParseValue<float>( xScale->Attribute( "variation" ) );
        xScale->Clear( );
    }
    xPart->Clear( );
    return true;
}

bool ParticleSystemParser::ParseEmiter(TiXML::TiXmlElement* xEmiter)
{
    if( !xEmiter )
    {
        return false;
    }

    emiter.spawnRadius.Set( ParseValue<Math::Vector2F > ( xEmiter->Attribute( "radius" ) ) );
    emiter.defaultRelPosition.Set( ParseValue<Math::Vector2F > ( xEmiter->Attribute( "relPosition" ) ) );

    {
        TiXML::TiXmlElement* xForce = xEmiter->FirstChildElement( "InitialForce" );

        TiXML::TiXmlElement* xMin = xForce->FirstChildElement( "MinValue" );
        emiter.minInitialForceMagnitude = ParseValue<float>( xMin->Attribute( "force" ) );
        emiter.minInitialForceAngle = ParseValue<float>( xMin->Attribute( "direction" ) );
        xMin->Clear( );

        TiXML::TiXmlElement* xMax = xForce->FirstChildElement( "MaxValue" );
        emiter.maxInitialForceMagnitude = ParseValue<float>( xMax->Attribute( "force" ) );
        emiter.maxInitialForceAngle = ParseValue<float>( xMax->Attribute( "direction" ) );
        xMin->Clear( );
        xForce->Clear( );
    }
    {
        TiXML::TiXmlElement* xVelocity = xEmiter->FirstChildElement( "InitialVelocity" );

        TiXML::TiXmlElement* xMin = xVelocity->FirstChildElement( "MinValue" );
        emiter.minInitialVelocityMagnitude = ParseValue<float>( xMin->Attribute( "force" ) );
        emiter.minInitialVelocityAngle = ParseValue<float>( xMin->Attribute( "direction" ) );
        xMin->Clear( );

        TiXML::TiXmlElement* xMax = xVelocity->FirstChildElement( "MaxValue" );
        emiter.maxInitialVelocityMagnitude = ParseValue<float>( xMax->Attribute( "force" ) );
        emiter.maxInitialVelocityAngle = ParseValue<float>( xMax->Attribute( "direction" ) );
        xMax->Clear( );
        xVelocity->Clear( );
    }
    xEmiter->Clear( );
    return true;
}

};
